﻿namespace NTLib.Core.UTest.Threading
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using NTLib.Core.Threading;
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;

    [TestClass]
    public class AsyncLockTest
    {
        #region Methods

        [TestCategory("Core.Threading")]
        [TestMethod]
        public void AsyncLock_Default()
        {
            AsyncLock locker = new AsyncLock();

            var wOne = locker.WaitOneAsync();
            var wTwo = locker.WaitOneAsync();
            Assert.IsTrue(wOne.IsCompleted);
            Assert.IsFalse(wTwo.IsCompleted);

            locker.ReleaseOne();
            Assert.IsTrue(wTwo.IsCompleted);
        }


        [TestCategory("Core.Threading")]
        [TestMethod]
        public void AsyncLock_ScopeLock()
        {
            Task.Run(async () =>
            {
                AsyncLock locker = new AsyncLock();
                Task wtwo = null;
                using (var wOne = await locker.LockAsync())
                {
                    wtwo = locker.WaitOneAsync();
                    Assert.IsFalse(wtwo.IsCompleted);
                }
                Assert.IsTrue(wtwo.IsCompleted);
            }).Wait();
        }

        [TestCategory("Core.Threading")]
        [TestMethod]
        public void AsyncLock_Cancellation()
        {
            AsyncLock locker = new AsyncLock();
            CancellationTokenSource source = new CancellationTokenSource();

            var wOne = locker.WaitOneAsync();
            var wTwo = locker.WaitOneAsync();
            var wTree = locker.WaitOneAsync(source.Token);
            var wFour = locker.WaitOneAsync();
            Assert.IsTrue(wOne.IsCompleted);
            Assert.IsFalse(wTwo.IsCompleted);
            Assert.IsFalse(wTree.IsCompleted);
            Assert.IsFalse(wFour.IsCompleted);

            source.Cancel();
            try
            {
                wTree.Wait();
            }
            catch
            {

            }
            Assert.IsTrue(wOne.IsCompleted);
            Assert.IsFalse(wTwo.IsCompleted);
            Assert.IsTrue(wTree.IsCanceled);
            Assert.IsFalse(wFour.IsCompleted);

            locker.ReleaseOne();
            Assert.IsTrue(wTwo.IsCompleted);
            Assert.IsFalse(wFour.IsCompleted);

            locker.ReleaseOne();
            Assert.IsTrue(wOne.IsCompleted);
            Assert.IsTrue(wTwo.IsCompleted);
            Assert.IsTrue(wTree.IsCanceled);
            Assert.IsTrue(wFour.IsCompleted);
        }

        #endregion
    }
}
